﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
using IBatisNet.DataMapper;
using System.Reflection;
using IBatisNet.DataMapper.Configuration;
using System.IO;

namespace KingSite.SyncDB.Core.Repository {
    public class BaseProvider : IbatisBase {
        public BaseProvider(string connectionStringName, DBType dbType) : base("KingSite.SyncDB.Core", connectionStringName, dbType) { }

        public BaseProvider() : base("KingSite.SyncDB.Core", Config.GetConnectionName(), Config.GetDBType()) { }

        private static ISqlMapper _sqlMapper;

        public ISqlMapper SqlMapper {
            get {
                if (_sqlMapper == null) {
                    _sqlMapper = base.GetSqlMapperInstance();
                }
                return _sqlMapper;
            }
        }

        protected void CPage(int pageIndex, int pageSize, int recordCount, out int startRow, out int endRow) {
            pageSize = Math.Abs(pageSize);
            int r = 0;
            int pageCount = Math.DivRem(recordCount, pageSize, out r);
            pageCount = r > 0 ? pageCount + 1 : pageCount;
            pageIndex = pageIndex > pageCount ? pageCount : pageIndex;
            pageIndex = pageIndex <= 0 ? 1 : pageIndex;
            startRow = (pageIndex - 1) * pageSize;
            endRow = pageIndex * pageSize > recordCount ? recordCount : pageIndex * pageSize;
        }

    }

    public abstract class IbatisBase {
        private string _dalAssemblyName;
        private string _connectionStringName;
        private bool _isConnStringEncrypt;
        private DBType _dbType;
        public DBType DbType {
            get { return _dbType; }
            set { _dbType = value; }
        }
        public string ConnectionStringName {
            get { return _connectionStringName; }
            set { _connectionStringName = value; }
        }
        public bool IsConnStringEncrypt {
            get { return _isConnStringEncrypt; }
            set { _isConnStringEncrypt = value; }
        }

        public IbatisBase(string dalAssemblyName, string connectionStringName) {
            if (String.IsNullOrEmpty(dalAssemblyName)) throw new ArgumentException("Value cannot be null or empty.", "dalAssemblyName");
            if (String.IsNullOrEmpty(connectionStringName)) throw new ArgumentException("Value cannot be null or empty.", "connectionStringName");

            _dalAssemblyName = dalAssemblyName;
            _connectionStringName = connectionStringName;
            string stype = ConfigurationManager.AppSettings["DBType"];
            if (string.IsNullOrEmpty(stype)) {
                stype = "sqlite3";
            }
            switch (stype.ToLower()) {
                case "sqlserver": _dbType = DBType.SqlServer; break;
                case "mysql": _dbType = DBType.MySql; break;
                case "oracle": _dbType = DBType.Oracle; break;
                case "sqlite3": _dbType = DBType.SQLite3; break;
                default: _dbType = DBType.SqlServer; break;
            }          
        }

        public IbatisBase(string dalAssemblyName, string connectionStringName, DBType dbType) {
            _dalAssemblyName = dalAssemblyName;
            _connectionStringName = connectionStringName;
            _dbType = dbType;
        }

        public ISqlMapper GetSqlMapperInstance() {
            ISqlMapper sqlMapper = null;
            string sqlmap;
            sqlmap = _dbType.ToString();
            sqlmap = string.Format("{0}-{1}{2}", "SqlMap", sqlmap, ".config");
            try {
                Assembly assembly = Assembly.Load(_dalAssemblyName);
                Stream stream = assembly.GetManifestResourceStream(string.Format("{0}.{1}", _dalAssemblyName, sqlmap));
                DomSqlMapBuilder builder = new DomSqlMapBuilder();
                sqlMapper = builder.Configure(stream) as SqlMapper;
            }
            catch (Exception ex) {
                throw new Exception(string.Format("{0}程序集加载失败，请检查！错误信息：{1}", _dalAssemblyName, ex.Message)); ;
            }

            try {                
                    sqlMapper.DataSource.ConnectionString = ConfigurationManager.ConnectionStrings[_connectionStringName].ConnectionString;            
            }
            catch {
                throw new Exception(string.Format("请在web.config的connectionStrings配置节中增加 {0} 连接字符串。", _connectionStringName));
            }
            return sqlMapper;
        }
    }

    public enum DBType {
        SqlServer,
        MySql,
        Oracle,
        SQLite3
    }

}
